# -*- coding: utf-8 -*-
"""Provides log utility methods, mostly useful for getting and instantiating a log easily.

"""

import os.path, logging, logging.config, logging.handlers

DEBUG=logging.DEBUG
INFO=logging.INFO
WARN=logging.WARN
ERROR=logging.ERROR

_ROOT = None
_ONCE = {}


def _resolve_path(fname):
    """Expands all environment variables and tildes, returning the absolute path."""
    fname = os.path.expandvars(fname)
    fname = os.path.expanduser(fname)
    if fname.startswith("./"):
        fname = "%s%s" % (os.getcwd(), fname[1:])
    return os.path.abspath(fname)


def getLogger(target, ini = None, streaming = True, level = logging.DEBUG, outfile = None, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s"):
    """Returns the requested logger, loading the base config from the spec'd
    ini file if not already loaded.

    Note that there can be several nominees for an inifile by delimiting with
    a semicolon.

    If no root, and no configfile is found, then load from the kwargs:

    streaming - true if errors should print to the console
    level - default log level
    format - output format
    outfile - output filename (Format with a leading "/" for an absolute path, else relative to the current working dir, format like so for RotatingFileHandler fname:maxsize:maxcount)
    """

    global _ROOT

    if _ROOT is None:
        if ini:
            for inifile in ini.split(";"):
                inifile = _resolve_path(inifile)
                if os.path.exists(inifile):
                    logging.config.fileConfig(inifile)
                    _ROOT = logging.root
                    _ROOT.debug("loaded from %s", inifile)

    if _ROOT is None:

        if isinstance(level, dict):
            levels = level
            level = levels.pop('root', logging.DEBUG)
        else:
            levels = {}

        _ROOT = logging.root
        _ROOT.setLevel(level)
        formatter = logging.Formatter(format)

        if streaming:
            streamout = logging.StreamHandler()
            streamout.setLevel(level)
            streamout.setFormatter(formatter)
            _ROOT.addHandler(streamout)

        if outfile:
            parts = outfile.split(":")
            if len(parts) == 3:
                fname, sz, ct = parts
                fileout = logging.handlers.RotatingFileHandler(fname, maxBytes=sz, backupCount=ct)
            else:
                fileout = logging.FileHandler(outfile)

            fileout.setLevel(level)
            fileout.setFormatter(formatter)
            _ROOT.addHandler(fileout)

        for key in levels:
            l = getLogger(key)
            l.setLevel(levels[key])

        _ROOT.debug("loaded config")

    return logging.getLogger(target)


def warn_once(logger, key, *args):

    global _ONCE
    if not _ONCE.get(key, False):
        _ONCE[key] = True
        logger.warn(*args)
